/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package czStvDpds.graphics;

import czStvDpds.centrallogic.EventAbsorber;
import czStvDpds.i18n.Internationalization;
import czStvDpds.input.LWJGLKeyEvent;
import czStvDpds.input.LWJGLMouseEvent;
import czStvDpds.mapmanagment.AccesibleMap;
import czStvDpds.movement.AbstractPlayer;
import czStvDpds.movement.CollisionManager;
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Robot;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

/**
 *
 * @author divad
 */
public class GameWindow implements Drawing2D, MouseListener, MouseMotionListener, MouseWheelListener, KeyListener, ActionListener {

    private static GameWindow thisGameWindow;
    private JFrame window;
    public static final int GAME = 1;
    private int windowState = GameWindow.GAME;
    private JPanel pane;
    private ArrayList<AbstractPlayer> players;
    private Timer stepper;
    private AccesibleMap map;
    private int mX, mY;
    private boolean center;
    private EventAbsorber absorber;

    /**
     * vrátí okno aplikace, pokud existuje a pokud ne, vytvoří jeho novou
     * instanci a vrátí tu.
     *
     * @return
     */
    public static Drawing2D getDrawing() {
        if (thisGameWindow == null) {
            thisGameWindow = new GameWindow();
        }
        return thisGameWindow;
    }

    /**
     * konstruktor
     */
    private GameWindow() {
        this.window = new JFrame(Internationalization.translate("frameTitle"));
        this.window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.stepper = new Timer(25, this);
        this.stepper.setActionCommand("stepper");

        this.window.addKeyListener(this);
        this.window.addMouseListener(this);
        this.window.addMouseMotionListener(this);

//        this.window.addKeyListener((GamePane) this.pane);
//        this.window.addMouseListener((GamePane) this.pane);
//        this.window.addMouseMotionListener((GamePane) this.pane);

        this.players = new ArrayList();

        stepper.start();
    }

    public void addAbsorber(EventAbsorber e) {
        absorber = e;
        //window.addKeyListener(e);
    }

    /**
     * vrátí "vnitřek" okna podle předané hodnoty
     *
     * @param state status = GameWindow. ...
     * @return
     */
    private JPanel getWindowPane(int state) {
        if (state == GameWindow.GAME) {
            return new GamePane();
        }
        return null;
    }
/////////////////////// - listenery - ///////////////////////////////

    @Override
    public void addPlayer(AbstractPlayer p) {
        this.players.add(new VisiblePlayer2D(p));
    }

    @Override
    public void mapChange() {
    }

    @Override
    public void playerMove(AbstractPlayer p) {
    }

    @Override
    public void removePlayer(AbstractPlayer p) {
        for (AbstractPlayer player : this.players) {
            VisiblePlayer2D visiblePlayer = (VisiblePlayer2D) player;
            if (((VisiblePlayer2D) player).getPlayer() == p) {
                this.players.remove(player);
                return;
            }
        }
    }

    @Override
    public void setMapData(AccesibleMap map) {
        this.map = map;
    }
//    nastaví, co bude okno zobrazovat (hru, menu, nastavení, ...)

    @Override
    public void setWindowState(int state) {
        this.windowState = state;
        this.window.getContentPane().removeAll();
        this.pane = getWindowPane(state);
        this.window.add(pane, BorderLayout.CENTER);
        this.window.pack();
        this.window.setLocationRelativeTo(null);
        if (this.pane != null) {
            this.window.setVisible(true);
        } else {
            this.window.setVisible(false);
        }
    }

    public ArrayList<AbstractPlayer> getPlayers() {
        return this.players;
    }

    public AccesibleMap getMap() {
        return this.map;
    }

    public void refresh() {
        this.window.pack();
        this.window.setLocationRelativeTo(null);
//        this.window.repaint();
    }

    @Override
    public void mouseEntered(MouseEvent e) {
//        System.out.println("mouse entered");
//        try {
////            new Robot().mouseMove(Display.getX()+(Display.getWidth()/2), Display.getY()+(Display.getHeight()/2));
//            new Robot().mouseMove((int) (this.window.getLocationOnScreen().getX() + (this.window.getWidth() / 2)), (int) (this.window.getLocationOnScreen().getY() + (this.window.getHeight() / 2)));
//            this.mX = (int) (this.window.getLocationOnScreen().getX() + (this.window.getWidth() / 2));
//            this.mY = (int) (this.window.getLocationOnScreen().getY() + (this.window.getHeight() / 2));
//        } catch (AWTException ex) {
////            Logger.getLogger(GamePane.class.getName()).log(Level.SEVERE, null, ex);
//            Logging.getMainLogger().log(Level.SEVERE, null, ex);
//        }
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void mouseMoved(MouseEvent e) {
//        System.out.println("mouse moved x=" + e.getX() + ",y=" + e.getY());

        if (center) {
            LWJGLMouseEvent me = new LWJGLMouseEvent(0, false, e.getXOnScreen() - mX, e.getYOnScreen() - mY, e.getXOnScreen(), e.getYOnScreen(), 0, -1);
            try {
                new Robot().mouseMove((int) (this.window.getLocationOnScreen().getX() + (this.window.getWidth() / 2)), (int) (this.window.getLocationOnScreen().getY() + (this.window.getHeight() / 2)));
            } catch (AWTException ex) {
                Logger.getLogger(GamePane.class.getName()).log(Level.SEVERE, null, ex);
            }


            for (AbstractPlayer player : players) {
                ((VisiblePlayer2D) player).mouseAction(me);
            }
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {
//        System.out.println("mouse pressed");
//        for (AbstractPlayer player : players) {
//            player.handleMousePress(e);
//        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
//        System.out.println("mouse released");
//        for (AbstractPlayer player : players) {
//            player.handleMouseRelease(e);
//        }
    }

    @Override
    public void keyPressed(KeyEvent e) {
//        System.out.println("key pressed");
        LWJGLKeyEvent le = null;
        if (e.getKeyCode() == KeyEvent.VK_W) {
            le = new LWJGLKeyEvent(LWJGLKeyEvent.KEY_W, 'w', true, -1);
        } else if (e.getKeyCode() == KeyEvent.VK_S) {
            le = new LWJGLKeyEvent(LWJGLKeyEvent.KEY_S, 's', true, -1);
        } else if (e.getKeyCode() == KeyEvent.VK_A) {
            le = new LWJGLKeyEvent(LWJGLKeyEvent.KEY_A, 'a', true, -1);
        } else if (e.getKeyCode() == KeyEvent.VK_D) {
            le = new LWJGLKeyEvent(LWJGLKeyEvent.KEY_D, 'd', true, -1);
        } else if (e.getKeyCode() == KeyEvent.VK_E) {
            this.center = !this.center;
            this.mX = (int) (this.window.getLocationOnScreen().getX() + (this.window.getWidth() / 2));
            this.mY = (int) (this.window.getLocationOnScreen().getY() + (this.window.getHeight() / 2));
        } else if (e.getKeyCode() == KeyEvent.VK_T) {
            for (AbstractPlayer player : players) {
                System.out.println("x: " + player.getX() + ", y: " + player.getY());
                System.out.println(CollisionManager.getCollisionManager().isShapeCollision(player.getX(), player.getY()) + "(shape collision)");
            }
        }

        if (le != null) {
            for (AbstractPlayer player : players) {
                ((VisiblePlayer2D) player).keyAction(le);
            }
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
//        System.out.println("key released");
        LWJGLKeyEvent le = null;
        if (e.getKeyCode() == KeyEvent.VK_W) {
            le = new LWJGLKeyEvent(LWJGLKeyEvent.KEY_W, 'w', false, -1);
        } else if (e.getKeyCode() == KeyEvent.VK_S) {
            le = new LWJGLKeyEvent(LWJGLKeyEvent.KEY_S, 's', false, -1);
        } else if (e.getKeyCode() == KeyEvent.VK_A) {
            le = new LWJGLKeyEvent(LWJGLKeyEvent.KEY_A, 'a', false, -1);
        } else if (e.getKeyCode() == KeyEvent.VK_D) {
            le = new LWJGLKeyEvent(LWJGLKeyEvent.KEY_D, 'd', false, -1);
        }

        if (le != null) {
            for (AbstractPlayer player : players) {
                ((VisiblePlayer2D) player).keyAction(le);
            }
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void mouseDragged(MouseEvent e) {
    }

    @Override
    public void mouseClicked(MouseEvent e) {
    }

    @Override
    public void mouseWheelMoved(MouseWheelEvent e) {
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getActionCommand().compareTo("stepper") == 0) {
            this.pane.repaint();
            for (AbstractPlayer p : players) {
                p.step();
            }
        }
    }
}
